package com.fw.mediasession.media.player;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.media.RatingCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;

import androidx.annotation.Nullable;

import com.fw.mediasession.media.bean.BaseBean;
import com.fw.mediasession.media.mediasession.MediaSessionConstants;
import com.fw.mediasession.media.mediasession.sessionutils.MediaSessionToClient;
import com.google.android.exoplayer2.DeviceInfo;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
import com.google.android.exoplayer2.video.VideoSize;
import com.orhanobut.logger.Logger;
import com.zy.untils.AppExecutors;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import javax.inject.Inject;
import javax.inject.Singleton;

import dagger.hilt.android.qualifiers.ApplicationContext;


@Singleton
public class ExoMediaPlayerUSB implements MediaPlayerFunction {
    public final Context context;
    public ExoPlayer mediaPlayer;
    private String TAG2 = "MediaPlayerUSB back ";
    private ArrayList<BaseBean> currentMusics = new ArrayList<>();
    private int currentIndex = 0;
    public AppExecutors appExecutors;
    public MediaSessionCompat mediaSession;
    public MediaSessionToClient toClient;
    private Timer timer;
    private TimerTask timerTask;

    @Inject
    public ExoMediaPlayerUSB(@ApplicationContext Context applicationContext, AppExecutors appExecutors) {
        this.context = applicationContext;
        this.appExecutors = appExecutors;
        initPlayer();
    }
int currentMode=2;
    @Override
    public void initPlayer() {
        mediaPlayer = new ExoPlayer.Builder(context).build();
        mediaPlayer.addListener(listener);
        mediaPlayer.setRepeatMode(Player.REPEAT_MODE_ALL);
    }

    Player.Listener listener = new Player.Listener() {
        @Override
        public void onEvents(Player player, Player.Events events) {
            Player.Listener.super.onEvents(player, events);
            if (events.contains(Player.EVENT_MEDIA_ITEM_TRANSITION)){
                Logger.d(TAG2 + "onEvents events EVENT_MEDIA_ITEM_TRANSITION" );
                int currentMediaItemIndex = player.getCurrentMediaItemIndex();
                Logger.d(TAG2 + "onEvents currentMediaItemIndex"+currentMediaItemIndex );
                currentIndex=currentMediaItemIndex;
                Logger.d(TAG2 + "onEvents currentMusics.get(currentIndex)"+currentMusics.get(currentIndex).title );
                toClient.sendMediaInfo(currentMusics.get(currentIndex));
                toClient.updateIndex(currentIndex);
            }
        }

        @Override
        public void onTimelineChanged(Timeline timeline, int reason) {

            Player.Listener.super.onTimelineChanged(timeline, reason);
        }

        @Override
        public void onMediaItemTransition(@Nullable com.google.android.exoplayer2.MediaItem mediaItem, int reason) {
            Player.Listener.super.onMediaItemTransition(mediaItem, reason);
            Logger.d(TAG2 + "onMediaItemTransition mediaMetadata" + mediaItem + ",reason" + reason);

        }

        @Override
        public void onTracksInfoChanged(TracksInfo tracksInfo) {
            Player.Listener.super.onTracksInfoChanged(tracksInfo);
        }

        @Override
        public void onMediaMetadataChanged(com.google.android.exoplayer2.MediaMetadata mediaMetadata) {
            Logger.d(TAG2 + "onMediaMetadataChanged mediaMetadata" + mediaMetadata);
            Player.Listener.super.onMediaMetadataChanged(mediaMetadata);

        }

        @Override
        public void onPlaylistMetadataChanged(com.google.android.exoplayer2.MediaMetadata mediaMetadata) {
            Logger.d(TAG2 + "onPlaylistMetadataChanged mediaMetadata" + mediaMetadata);
            Player.Listener.super.onPlaylistMetadataChanged(mediaMetadata);
        }

        @Override
        public void onIsLoadingChanged(boolean isLoading) {
            Player.Listener.super.onIsLoadingChanged(isLoading);
        }

        @Override
        public void onAvailableCommandsChanged(Player.Commands availableCommands) {
            Player.Listener.super.onAvailableCommandsChanged(availableCommands);
        }

        @Override
        public void onTrackSelectionParametersChanged(TrackSelectionParameters parameters) {
            Player.Listener.super.onTrackSelectionParametersChanged(parameters);
        }

        @Override
        public void onPlaybackStateChanged(int playbackState) {
            Logger.d(TAG2 + "onPlaybackStateChanged playbackState" + playbackState);
            Player.Listener.super.onPlaybackStateChanged(playbackState);
            sendMessageToClient(playbackState);
            updateTime(playbackState);
        }

        @Override
        public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) {
            Logger.d(TAG2 + "onPlayWhenReadyChanged playWhenReady" + playWhenReady);
            Player.Listener.super.onPlayWhenReadyChanged(playWhenReady, reason);
        }

        @Override
        public void onPlaybackSuppressionReasonChanged(int playbackSuppressionReason) {
            Player.Listener.super.onPlaybackSuppressionReasonChanged(playbackSuppressionReason);
        }

        @Override
        public void onIsPlayingChanged(boolean isPlaying) {
            Logger.d(TAG2 + "onIsPlayingChanged isPlaying" + isPlaying);
            Player.Listener.super.onIsPlayingChanged(isPlaying);
        }

        @Override
        public void onRepeatModeChanged(int repeatMode) {
            Logger.d(TAG2 + "onRepeatModeChanged repeatMode" + repeatMode);
            Player.Listener.super.onRepeatModeChanged(repeatMode);
        }

        @Override
        public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
            Player.Listener.super.onShuffleModeEnabledChanged(shuffleModeEnabled);
        }

        @Override
        public void onPlayerError(PlaybackException error) {
            Logger.d(TAG2 + "onPlayerError PlaybackException" + error);
            Player.Listener.super.onPlayerError(error);
            toClient.sendMediaState(1, 0);
            onSkipToNext();
        }

        @Override
        public void onPlayerErrorChanged(@Nullable PlaybackException error) {
            Logger.d(TAG2 + "onPlayerErrorChanged PlaybackException" + error);
            Player.Listener.super.onPlayerErrorChanged(error);
        }

        @Override
        public void onPositionDiscontinuity(Player.PositionInfo oldPosition, Player.PositionInfo newPosition, int reason) {
            Player.Listener.super.onPositionDiscontinuity(oldPosition, newPosition, reason);
        }

        @Override
        public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
            Player.Listener.super.onPlaybackParametersChanged(playbackParameters);
        }

        @Override
        public void onSeekBackIncrementChanged(long seekBackIncrementMs) {
            Player.Listener.super.onSeekBackIncrementChanged(seekBackIncrementMs);
        }

        @Override
        public void onSeekForwardIncrementChanged(long seekForwardIncrementMs) {
            Player.Listener.super.onSeekForwardIncrementChanged(seekForwardIncrementMs);
        }

        @Override
        public void onMaxSeekToPreviousPositionChanged(long maxSeekToPreviousPositionMs) {
            Player.Listener.super.onMaxSeekToPreviousPositionChanged(maxSeekToPreviousPositionMs);
        }

        @Override
        public void onAudioSessionIdChanged(int audioSessionId) {
            Player.Listener.super.onAudioSessionIdChanged(audioSessionId);
        }

        @Override
        public void onAudioAttributesChanged(AudioAttributes audioAttributes) {
            Player.Listener.super.onAudioAttributesChanged(audioAttributes);
        }

        @Override
        public void onVolumeChanged(float volume) {
            Logger.d(TAG2 + "onVolumeChanged volume" + volume);
            Player.Listener.super.onVolumeChanged(volume);
        }

        @Override
        public void onSkipSilenceEnabledChanged(boolean skipSilenceEnabled) {
            Player.Listener.super.onSkipSilenceEnabledChanged(skipSilenceEnabled);
        }

        @Override
        public void onDeviceInfoChanged(DeviceInfo deviceInfo) {
            Player.Listener.super.onDeviceInfoChanged(deviceInfo);
        }

        @Override
        public void onDeviceVolumeChanged(int volume, boolean muted) {
            Logger.d(TAG2 + "onDeviceVolumeChanged volume" + volume);
            Player.Listener.super.onDeviceVolumeChanged(volume, muted);
        }

        @Override
        public void onVideoSizeChanged(VideoSize videoSize) {
            Logger.d(TAG2 + "onVideoSizeChanged VideoSize" + videoSize);
            Player.Listener.super.onVideoSizeChanged(videoSize);
        }

        @Override
        public void onSurfaceSizeChanged(int width, int height) {
            Logger.d(TAG2 + "onSurfaceSizeChanged width" + width);
            Player.Listener.super.onSurfaceSizeChanged(width, height);
        }

        @Override
        public void onRenderedFirstFrame() {
            Logger.d(TAG2 + "onRenderedFirstFrame");
            Player.Listener.super.onRenderedFirstFrame();
        }

        @Override
        public void onCues(List<Cue> cues) {
            Player.Listener.super.onCues(cues);
        }

        @Override
        public void onMetadata(Metadata metadata) {
            Logger.d(TAG2 + "onMetadata Metadata" + metadata);
            Player.Listener.super.onMetadata(metadata);
        }
    };

    @Override
    public void releasePlayer() {
        if (mediaPlayer != null) {
            sendMessageToClient(PlaybackStateCompat.STATE_PAUSED);
            mediaPlayer.removeListener(listener);
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }

    public void sendMessageToClient(int state) {
        toClient.sendMediaState(state, mediaPlayer.getCurrentPosition());
    }

    @Override
    public void setMediaSessionToClientManager(MediaSessionToClient manager) {
        toClient = manager;
    }

    @Override
    public void onPlayFromMediaId(MediaSessionCompat mediaSession, String mediaId, Bundle extras) {
        Logger.d(TAG2 + "onPlayFromMediaId： MediaSessionCompat" + mediaSession + ",mediaId: " + mediaId + ", Bundle" + extras);
        if (mediaPlayer != null) {
            mediaPlayer.removeMediaItems(0, mediaPlayer.getMediaItemCount());
            int anInt = extras.getInt(MediaSessionConstants.QUEUE_TYPE);
            ArrayList<BaseBean> medias = (ArrayList<BaseBean>) extras.getSerializable(MediaSessionConstants.QUEUE_LIST);
            switch (anInt) {
                case 0://music
                    break;
                case 1://video
                    break;
                case 2://picture
                    break;
            }
            if (medias != null && medias.size() > 0) {
                currentMusics.clear();
                currentMusics.addAll(medias);
                for (int i = 0; i < medias.size(); i++) {
                    BaseBean baseBean = medias.get(i);
                    if (baseBean.ID.equals(mediaId)) {
                        currentIndex = i;
                    }
                    MediaItem mediaItem = MediaItem.fromUri(Uri.parse(medias.get(i).filePath));
                    mediaPlayer.addMediaItem(mediaItem);
                }
//                toClient.sendMediaInfo(medias.get(currentIndex));
                mediaPlayer.seekToDefaultPosition(currentIndex);
                onPlay();
            }


        } else {
            Logger.d("mediaPlayer为null！！");
        }
    }

    @Override
    public void onSkipToQueueItem(long id) {
//        mediaPlayer.skipToPlaylistItem((int) id);
        Logger.d(TAG2 + "onSkipToQueueItem： id" + id);
    }

    @Override
    public void onPlay() {
        Logger.d(TAG2 + "onPlay：");
        if (mediaPlayer != null) {
            mediaPlayer.prepare();

            mediaPlayer.play();

            sendMessageToClient(PlaybackStateCompat.STATE_PLAYING);
        } else {
            Logger.d("mediaPlayer为null！！");
        }
    }

    @Override
    public void onPause() {
        Logger.d(TAG2 + "onPause：");
        if (mediaPlayer != null) {
            mediaPlayer.pause();
            sendMessageToClient(PlaybackStateCompat.STATE_PAUSED);
        } else {
            Logger.d("mediaPlayer为null！！");
        }
    }

    @Override
    public void onStop() {
        Logger.d(TAG2 + "onStop：");
        if (mediaPlayer != null) {
            mediaPlayer.stop();
            toClient.sendMediaState(1, mediaPlayer.getCurrentPosition());
        } else {
            Logger.d("mediaPlayer为null！！");
        }
    }

    @Override
    public void onSkipToNext() {
        Logger.d(TAG2 + "onSkipToNext：");
        if (mediaPlayer != null) {
            if(currentMode==3){
                Random r = new Random();
                currentIndex=r.nextInt(currentMusics.size());
                mediaPlayer.seekToDefaultPosition(currentIndex);
            }else{

                mediaPlayer.seekToNext();
            }
            if (!mediaPlayer.isPlaying()) {
                onPlay();
            }
//            int currentMediaItemIndex = mediaPlayer.getCurrentMediaItemIndex();
//            BaseBean baseBean = currentMusics.get(currentMediaItemIndex);
//            toClient.sendMediaInfo(baseBean);
        } else {
            Logger.d("mediaPlayer为null！！");
        }
    }

    @Override
    public void onSkipToPrevious() {
        Logger.d(TAG2 + "onSkipToPrevious：");
        if (mediaPlayer != null) {
//            if(currentMode==3){
//                Random r = new Random();
//                currentIndex=r.nextInt(currentMusics.size());
//                mediaPlayer.seekToDefaultPosition(currentIndex);
//            }else{
//
//
//                mediaPlayer.seekToPrevious();
//            }
                mediaPlayer.seekToPrevious();
            if (!mediaPlayer.isPlaying()) {
                onPlay();
            }
//            int currentMediaItemIndex = mediaPlayer.getCurrentMediaItemIndex();
//            BaseBean baseBean = currentMusics.get(currentMediaItemIndex);
//            toClient.sendMediaInfo(baseBean);
        } else {
            Logger.d("mediaPlayer为null！！");
        }
    }

    @Override
    public void onPrepare() {

    }

    @Override
    public void onSeekTo(Long pos) {
        Logger.d(TAG2 + "onSeekTo：pos" + pos);
        if (mediaPlayer != null) {
            mediaPlayer.seekTo(pos);
            if (!mediaPlayer.isPlaying()) {
                onPlay();
            }
        } else {
            Logger.d("mediaPlayer为null！！");
        }
    }

    @Override
    public void setPlaySpeed(float speed) {
        Logger.d(TAG2 + "setPlaySpeed：speed" + speed);
        if (mediaPlayer != null) {
        } else {
            Logger.d("mediaPlayer为null！！");
        }
    }

    @Override
    public void onSetRepeatMode(MediaSessionCompat mediaSession, int repeatMode) {
        Logger.d(TAG2 + "onSetRepeatMode：repeatMode" + repeatMode);
        if (mediaPlayer != null) {
            currentMode=repeatMode;
            if(repeatMode==3){
                mediaPlayer.setRepeatMode(Player.REPEAT_MODE_ALL);
            }else{
                mediaPlayer.setRepeatMode(repeatMode);
            }
        } else {
            Logger.d("mediaPlayer为null！！");
        }
    }

    @Override
    public void onSetRating(MediaSessionCompat mediaSession, RatingCompat rating) {
        Logger.d(TAG2 + "onSetRating：RatingCompat" + rating);
        if (mediaPlayer != null) {
        } else {
            Logger.d("mediaPlayer为null！！");
        }
    }

    @Override
    public void onSetRating(MediaSessionCompat mediaSession, RatingCompat rating, Bundle extras) {
        Logger.d(TAG2 + "onSetRating：RatingCompat" + rating + " Bundle" + extras);
        if (mediaPlayer != null) {
        } else {
            Logger.d("mediaPlayer为null！！");
        }
    }

    @Override
    public void onPrepareFromSearch(String query, Bundle extras) {
        Logger.d(TAG2 + "onPrepareFromSearch：query" + query + " Bundle" + extras);
    }

    @Override
    public void onPlayFromSearch(String query, Bundle extras) {
        Logger.d(TAG2 + "onPlayFromSearch：query" + query + " Bundle" + extras);
    }

    @Override
    public void onPrepareFromUri(Uri uri, Bundle extras) {
        Logger.d(TAG2 + "onPrepareFromUri：Uri" + uri + " Bundle" + extras);
    }

    @Override
    public void onPlayFromUri(Uri uri, Bundle extras) {
        Logger.d(TAG2 + "onPlayFromUri：Uri" + uri + " Bundle" + extras);
    }

    @Override
    public void onCustomAction(MediaSessionCompat mediaSession, String action, Bundle extras) {
        Logger.d(TAG2 + "onPlayFromUri：action" + action + " Bundle" + extras);
    }

    @Override
    public void onFastForward() {

    }

    @Override
    public void onRewind() {

    }


    void startUpdatePosition() {
        if (timer == null) {
            timer = new Timer();
            timerTask = new TimerTask() {
                @Override
                public void run() {
                    if (mediaPlayer != null) {
                        appExecutors.mainThread().execute(new Runnable() {
                            @Override
                            public void run() {
                                toClient.updatePlayPosition((int) mediaPlayer.getCurrentPosition());
                            }
                        });

                    }
                }
            };
        }
        timer.schedule(timerTask, 0, 1000);

    }

    void stopUpdatePosition() {
        if(timerTask!=null){
            timerTask.cancel();
            timerTask=null;
        }
        if (timer != null) {
            timer.cancel();
            timer=null;
        }
    }

    public void updateTime(int state) {
        if (state == PlaybackStateCompat.STATE_PLAYING) {
            Logger.d(TAG2+"startUpdatePosition");
            startUpdatePosition();
        } else {
            stopUpdatePosition();
            Logger.d(TAG2+"stopUpdatePosition");
        }
    }
}
